package pikes.xml;

import java.io.PrintWriter;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import pikes.core.Printable;
import pikes.core.TextView;

/**
 * Abstract view which renders a XML document to the response's writer. Subclasses should provide a root tag and doc
 * type. The user of this class can set the following properties: <code>
 * <ul>
 *  <li><code>format</code>. Sets printing format configuration. If null, {@link XMLFormattingConfiguration#SIMPLE} will be used.</li>
 *  <li><code>encoding</code>. Sets the generated XML document's encoding. Can be null.</li>
 * </ul>
 * </code>
 * @author Peter Bona
 * @since 0.1.0
 */
public abstract class XMLDocumentView extends TextView {

	private XMLFormattingConfiguration format = XMLFormattingConfiguration.SIMPLE;

	private CharSequence encoding = null;

	private DocType docType = null;

	@Override
	protected final Printable createContent(Map model, HttpServletRequest request) throws Exception {
		XMLTag rootTag = createRootTag(model, request);

		XMLDocument xmlDocument = new XMLDocument(rootTag, getDocType(), encoding);

		return xmlDocument;
	}

	@Override
	protected final void printContent(Printable printable, PrintWriter responseWriter) throws Exception {

		XMLDocument xmlDocument = (XMLDocument) printable;

		XMLVisitor xmlPrinter = format.createXMLPrinter(responseWriter);
		xmlDocument.visit(xmlPrinter);
	}

	/**
	 * Creates the root tag for the XML document
	 * @param model
	 * @param request
	 * @return the root tag
	 * @throws Exception
	 */
	protected abstract XMLTag createRootTag(Map model, HttpServletRequest request) throws Exception;

	/**
	 * Provides document type declaration.
	 * @return the doc type
	 */
	public final DocType getDocType() {
		return docType;
	}

	/**
	 * Provides document type declaration.
	 * @param docType
	 */
	public final void setDocType(DocType docType) {
		this.docType = docType;
	}

	/**
	 * @return printing format configuration
	 */
	public final XMLFormattingConfiguration getFormat() {
		return format;
	}

	/**
	 * Sets printing format configuration
	 * @param printerConfig the formatting configuration. If null {@link XMLFormattingConfiguration#SIMPLE} will be
	 * used.
	 */
	public final void setFormat(XMLFormattingConfiguration printerConfig) {
		if (printerConfig == null) {
			this.format = XMLFormattingConfiguration.SIMPLE;
		}
		else {
			this.format = printerConfig;
		}
	}

	public final CharSequence getEncoding() {
		return encoding;
	}

	public final void setEncoding(CharSequence encoding) {
		this.encoding = encoding;
	}
}
